<!--
 * @Author: lihaogn
 * @Date: 2021-09-10 00:15:45
 * @LastEditTime: 2021-09-26 21:23:26
 * @LastEditor: lihaogn
 * @Description: 虚拟滚动
 * @FilePath: \lix-management\src\views\experiment\VirtualScroll.vue
-->

<template>
  <div>
    <div class="gl-cell-card-box">
      <el-table
        ref="tableRef"
        style="width:418px"
        border
        max-height="448"
        :data="sliceTable"
        :row-key="row => row.id"
        @select="handleSelect"
        @select-all="handleSelectAll"
      >
        <el-table-column type="selection" width="40"> </el-table-column>
        <el-table-column prop="name" label="姓名" width="120"></el-table-column>
        <el-table-column prop="age" label="年龄" width="120"></el-table-column>
        <el-table-column prop="address" label="住址"></el-table-column>
      </el-table>
    </div>

    <!-- div 的例子 -->
    <div class="gl-cell-card-box" style="margin-top:10px;">
      <div
        class="list"
        style="height: 300px;overflow: scroll"
        ref="scrollDom"
        @scroll="scroll"
      >
        <div :style="{ height: list.length * 40 + 'px' }">
          <div
            style="position:absolute;width: 100%"
            :style="{ top: startIndex1 * 40 + 'px' }"
          >
            <div v-for="(item, index) in splitData" :key="index" class="item">
              <div v-html="item.id"></div>
              <div v-html="item.name"></div>
              <div v-html="item.createTime"></div>
              <div>
                <Button>修改</Button>
                <Button>删除</Button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      // 表格所有数据
      tableData: [],
      // 开始索引
      startIndex: 0,
      // 选中的数据
      selectedRows: [],
      // 空元素，用于撑开table的高度
      vEle: undefined,
      // 是否全选
      isSelectedAll: false,
      // ===================== list =====================
      list: [],
      startIndex1: 0
    };
  },
  computed: {
    sliceTable() {
      return this.tableData.slice(this.startIndex, this.startIndex + 9);
    },
    // ===================== list =====================
    limitCount() {
      return 300 / 40 + 2;
    },
    splitData() {
      return this.list.slice(
        this.startIndex1,
        this.startIndex1 + this.limitCount
      );
    }
  },
  created() {
    // 创建一个空元素
    this.vEle = document.createElement("div");
    this.loadData();
    // ===================== list =====================
    for (let i = 0; i < 200; i++) {
      this.list.push({
        id: 1,
        name: "name" + i,
        createTime: "2018-09-09"
      });
    }
  },

  mounted() {
    // 绑定滚动事件
    this.$refs.tableRef.$el
      .querySelector(".el-table__body-wrapper")
      .addEventListener("scroll", this.tableScroll, {
        passive: true
      });
  },
  methods: {
    /**
     * @author: 李昊
     * @Date: 2021-09-25 16:23:54
     * @description: 加载数据
     * @param {*}
     * @return {*}
     */
    loadData() {
      let start_i = this.tableData.length;
      for (let i = start_i; i < start_i + 20; i++) {
        this.tableData.push({
          id: i,
          name: "zhangsan" + i,
          age: 12,
          address: "china"
        });
      }
      this.$nextTick(() => {
        this.$refs.tableRef.$el.querySelector(
          ".el-table__body"
        ).style.position = "absolute";
        this.vEle.style.height = this.tableData.length * 48 + "px";
        this.$refs.tableRef.$el
          .querySelector(".el-table__body-wrapper")
          .appendChild(this.vEle);

        this.selectedRows.forEach(row => {
          this.$refs.tableRef.toggleRowSelection(row, true);
        });
      });
    },
    /**
     * @author: 李昊
     * @Date: 2021-09-26 10:23:03
     * @description: 手动勾选时的事件
     * @param {*} selection - 选中的所有数据
     * @param {*} row - 当前选中的数据
     * @return {*}
     */
    handleSelect(selection, row) {
      console.log("handleSelect ==> selection", selection, "row", row);
      this.selectedRows = selection;
    },
    /**
     * @author: 李昊
     * @Date: 2021-09-26 10:24:26
     * @description: 全选事件
     * @param {*} selection
     * @return {*}
     */
    handleSelectAll(selection) {
      console.log("handleSelectAll ==> selection", selection);
      this.isSelectedAll = !this.isSelectedAll;
      if (this.isSelectedAll) {
        this.selectedRows = this.tableData;
      } else {
        this.selectedRows = [];
        this.$refs.tableRef.clearSelection();
      }
    },

    /**
     * @author: 李昊
     * @Date: 2021-09-12 15:39:28
     * @description: table 滚动事件
     * @param {*}
     * @return {*}
     */
    tableScroll() {
      let bodyWrapperEle = this.$refs.tableRef.$el.querySelector(
        ".el-table__body-wrapper"
      );
      // 滚动的高度
      let scrollTop = bodyWrapperEle.scrollTop;
      // 下一次开始的索引
      this.startIndex = Math.floor(scrollTop / 48);
      // 滚动操作
      bodyWrapperEle.querySelector(
        ".el-table__body"
      ).style.transform = `translateY(${this.startIndex * 48}px)`;

      this.selectedRows.forEach(row => {
        this.$refs.tableRef.toggleRowSelection(row, true);
      });

      // 滚动到底，加载新数据
      if (
        bodyWrapperEle.scrollHeight <=
        scrollTop + bodyWrapperEle.clientHeight
      ) {
        if (this.tableData.length == 100) {
          this.$message.warning("没有更多了");
          return;
        }
        this.loadData();
      }
    },
    /**
     * @author: 李昊
     * @Date: 2021-09-10 01:44:47
     * @description: list 的滚动事件
     * @param {*}
     * @return {*}
     */
    scroll() {
      // 根据滚动的距离，估算出这个滚动位置对应的数组序列，例如滚动100px，每条40px，对应第3条
      let scrollTop = this.$refs.scrollDom.scrollTop;
      this.startIndex1 = Math.floor(scrollTop / 40);
    }
  }
};
</script>
<style lang="less" scoped>
.list {
  border: solid 1px #5f5f5f;
  background-color: white;
  margin: 10px 0;
  padding: 5px;
  width: 500px;
  position: relative;

  .item {
    display: flex;
    height: 40px;

    > * {
      flex-grow: 1;
      border: solid 1px #9e9e9e;
      padding: 3px;
    }
  }
}
</style>
